package com.phei.netty.my.nonblocking;

import org.apache.tools.ant.taskdefs.Sleep;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

public class ReactorHandler implements Runnable{
    int port =8080;
    List<SocketChannel> clients = new ArrayList<SocketChannel>(5);
    ServerSocketChannel acceptor;
    public ReactorHandler(){
        try {
            // 创建serverSocketChannel实例
            acceptor = ServerSocketChannel.open();
            acceptor.socket().bind(new InetSocketAddress("127.0.0.1",port));
            // winsock: 只有nonblocking才可以使用 EventSelect 事件模型
            acceptor.configureBlocking(false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        for(;;){
            try {
                // 异步，不会阻塞线程
                SocketChannel client = acceptor.accept();
                Thread.sleep(1000);
                // serverSocketChannel没有新的连接，返回null
                if(client == null){
                    System.out.println("新连接-->没有新的连接接入...");
                }else{
                    client.configureBlocking(false);
                    clients.add(client);
                    System.out.println("新连接-->ok");
                }

                // 需要使用合适的缓存空间以便于将client发送的数据快速读完
                ByteBuffer buffer = ByteBuffer.allocate(50);
                clients.stream().forEach(c->{
                    try {
                        // 同步操作：直接返回结果：channel中没有数据：0，已断开：-1；
                        // 同步读取管道中的数据到 堆外内存（缓存）中，返回数据的长度
                        int count = c.read(buffer);
                        if(count>0){
                            // socketChannel c 有数据
                            buffer.flip();
                            byte[] data = new byte[count];
                            buffer.get(data,0,count);
                            System.out.println("数据> "+c.getRemoteAddress()+":"+c.socket()
                                    .getPort()+"["+new String(data)+"]");
                        }else if (count==-1){
                            System.out.println("断开> "+c.getRemoteAddress()+":"+c.socket()
                                    .getPort()+"已断开");
                            // 剔除
                            clients.remove(c);
                        }
                        buffer.clear();
                    } catch (IOException e) {

                    }
                });


            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
